package service

import (
	"bbs-web/internal/domain"
	"bbs-web/internal/repository"
	"bbs-web/internal/repository/cache"
	"context"
	"golang.org/x/sync/errgroup"
)

//go:generate mockgen -source=./interactive_service.go -package=svcmocks -destination=./svcmocks/interactive.mock.go
type InteractiveService interface {
	Get(ctx context.Context, biz string, id, uid int64) (domain.Interactive, error)
	Liked(ctx context.Context, biz string, id, uid int64) error
	DisLiked(ctx context.Context, biz string, id, uid int64) error
	Collected(ctx context.Context, biz string, id, uid int64) error
	DisCollected(ctx context.Context, biz string, id, uid int64) error
	GetByUid(ctx context.Context, id int64, offset, limit int) ([]domain.Collect, error)
	CreateCollect(ctx context.Context, uid int64, cname string, desc string, isPub bool) (int64, error)
	CollectEntity(ctx context.Context, biz string, uid, cid, bizId int64) error
	GetByIds(ctx context.Context, biz string, ids []int64) (map[int64]domain.Interactive, error)
}

type interactiveService struct {
	repo  repository.InteractiveRepo
	cache cache.RedisInteractiveCache
}

func NewInteractiveService(repo repository.InteractiveRepo, cache cache.RedisInteractiveCache) InteractiveService {
	return &interactiveService{repo: repo, cache: cache}
}

func (i *interactiveService) GetByIds(ctx context.Context, biz string, ids []int64) (map[int64]domain.Interactive, error) {
	return nil, nil
}

func (i *interactiveService) CollectEntity(ctx context.Context, biz string, uid, cid, bizId int64) error {
	return i.repo.CollectEntity(ctx, biz, uid, cid, bizId)
}

func (i *interactiveService) CreateCollect(ctx context.Context, uid int64, cname string, desc string, isPub bool) (int64, error) {
	return i.repo.CreateCollect(ctx, uid, cname, desc, isPub)
}

func (i *interactiveService) GetByUid(ctx context.Context, id int64, offset, limit int) ([]domain.Collect, error) {
	return i.repo.GetCollectListByID(ctx, id, limit, offset)
}

func (i *interactiveService) Collected(ctx context.Context, biz string, id, uid int64) error {
	return i.repo.IncrCollected(ctx, biz, id, uid)
}

func (i *interactiveService) DisCollected(ctx context.Context, biz string, id, uid int64) error {
	return i.repo.IncrDisCollected(ctx, biz, id, uid)
}

func (i *interactiveService) Liked(ctx context.Context, biz string, id, uid int64) error {
	return i.repo.IncrLiked(ctx, biz, id, uid)
}

func (i *interactiveService) DisLiked(ctx context.Context, biz string, id, uid int64) error {
	return i.repo.IncrDisLiked(ctx, biz, id, uid)
}

func (i *interactiveService) Get(ctx context.Context, biz string, id, uid int64) (domain.Interactive, error) {
	//使用errgroup，一个获取数量，一个获取喜欢状态，一个获取收藏状态
	var (
		eg        errgroup.Group
		intr      domain.Interactive
		liked     bool
		collected bool
	)

	//可以异步获取数量，评论数，点赞数
	eg.Go(func() error {
		var err error
		intr, err = i.repo.Get(ctx, biz, id)
		return err
	})
	//异步获取喜欢状态
	eg.Go(func() error {
		var err error
		liked, err = i.repo.Liked(ctx, biz, id, uid)
		return err
	})

	//异步获取收藏状态
	eg.Go(func() error {
		var err error
		collected, err = i.repo.Collection(ctx, biz, id, uid)
		return err
	})

	//wait之后组装整体的domain
	er := eg.Wait()
	if er != nil {
		return domain.Interactive{}, er
	}
	intr.Liked = liked
	intr.Collected = collected
	return intr, nil
}
